using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace GenerativeAgents.Core
{
    /// <summary>
    /// 路径查找器
    /// 负责在空间记忆中查找从起点到终点的最优路径
    /// </summary>
    public class PathFinder
    {
        private Dictionary<string, List<Vector3>> cachedPaths;
        private int maxCacheSize = 50;
        private float pathCacheLifetime = 300f; // 5分钟
        private Dictionary<string, DateTime> pathCacheTimestamps;
        
        public PathFinder()
        {
            InitializePathFinder();
        }
        
        /// <summary>
        /// 初始化路径查找器
        /// </summary>
        private void InitializePathFinder()
        {
            cachedPaths = new Dictionary<string, List<Vector3>>();
            pathCacheTimestamps = new Dictionary<string, DateTime>();
        }
        
        /// <summary>
        /// 查找路径
        /// </summary>
        public List<Vector3> FindPath(Vector3 start, Vector3 end, SpatialMemory spatialMemory)
        {
            try
            {
                // 检查缓存
                var cacheKey = GenerateCacheKey(start, end);
                if (TryGetCachedPath(cacheKey, out var cachedPath))
                {
                    return cachedPath;
                }
                
                // 执行路径查找
                var path = PerformPathfinding(start, end, spatialMemory);
                
                // 缓存结果
                CachePath(cacheKey, path);
                
                return path;
            }
            catch (Exception ex)
            {
                Debug.LogError($"[PathFinder] Error finding path from {start} to {end}: {ex.Message}");
                return CreateDirectPath(start, end);
            }
        }
        
        /// <summary>
        /// 执行路径查找算法
        /// </summary>
        private List<Vector3> PerformPathfinding(Vector3 start, Vector3 end, SpatialMemory spatialMemory)
        {
            if (spatialMemory == null)
            {
                return CreateDirectPath(start, end);
            }
            
            // 使用空间记忆系统查找路径
            var spatialPath = spatialMemory.FindPath(start, end);
            if (spatialPath != null && spatialPath.Count > 0)
            {
                return OptimizePath(spatialPath);
            }
            
            // 如果空间记忆无法提供路径，使用基于网格的A*算法
            return FindPathWithAStar(start, end, spatialMemory);
        }
        
        /// <summary>
        /// 使用A*算法查找路径
        /// </summary>
        private List<Vector3> FindPathWithAStar(Vector3 start, Vector3 end, SpatialMemory spatialMemory)
        {
            try
            {
                // 简化的A*实现，基于空间节点
                var openSet = new List<PathNode>();
                var closedSet = new HashSet<Vector3>();
                var cameFrom = new Dictionary<Vector3, Vector3>();
                
                var startNode = new PathNode
                {
                    position = start,
                    gScore = 0,
                    hScore = Vector3.Distance(start, end),
                    fScore = Vector3.Distance(start, end)
                };
                
                openSet.Add(startNode);
                
                while (openSet.Count > 0)
                {
                    // 找到F分数最低的节点
                    var current = openSet.OrderBy(n => n.fScore).First();
                    openSet.Remove(current);
                    
                    // 如果到达目标
                    if (Vector3.Distance(current.position, end) < 1f)
                    {
                        return ReconstructPath(cameFrom, current.position, start);
                    }
                    
                    closedSet.Add(current.position);
                    
                    // 检查邻居节点
                    var neighbors = GetNeighbors(current.position, spatialMemory);
                    foreach (var neighbor in neighbors)
                    {
                        if (closedSet.Contains(neighbor))
                            continue;
                        
                        var tentativeGScore = current.gScore + Vector3.Distance(current.position, neighbor);
                        
                        var neighborNode = openSet.FirstOrDefault(n => Vector3.Distance(n.position, neighbor) < 0.1f);
                        if (neighborNode == null)
                        {
                            neighborNode = new PathNode
                            {
                                position = neighbor,
                                gScore = tentativeGScore,
                                hScore = Vector3.Distance(neighbor, end),
                                fScore = tentativeGScore + Vector3.Distance(neighbor, end)
                            };
                            openSet.Add(neighborNode);
                            cameFrom[neighbor] = current.position;
                        }
                        else if (tentativeGScore < neighborNode.gScore)
                        {
                            neighborNode.gScore = tentativeGScore;
                            neighborNode.fScore = tentativeGScore + neighborNode.hScore;
                            cameFrom[neighbor] = current.position;
                        }
                    }
                    
                    // 防止无限循环
                    if (openSet.Count > 100)
                    {
                        break;
                    }
                }
                
                // 如果找不到路径，返回直线路径
                return CreateDirectPath(start, end);
            }
            catch (Exception ex)
            {
                Debug.LogError($"[PathFinder] Error in A* pathfinding: {ex.Message}");
                return CreateDirectPath(start, end);
            }
        }
        
        /// <summary>
        /// 获取邻居节点
        /// </summary>
        private List<Vector3> GetNeighbors(Vector3 position, SpatialMemory spatialMemory)
        {
            var neighbors = new List<Vector3>();
            
            try
            {
                // 基于空间记忆获取邻居
                if (spatialMemory != null)
                {
                    var nearbyNodes = spatialMemory.GetAllSpatialNodes().Values
                        .Where(n => Vector3.Distance(n.position, position) <= 10f && Vector3.Distance(n.position, position) > 0.1f)
                        .OrderBy(n => Vector3.Distance(n.position, position))
                        .Take(8);
                    
                    neighbors.AddRange(nearbyNodes.Select(n => n.position));
                }
                
                // 如果没有空间记忆邻居，使用网格邻居
                if (neighbors.Count == 0)
                {
                    var gridSize = 2f;
                    for (int x = -1; x <= 1; x++)
                    {
                        for (int z = -1; z <= 1; z++)
                        {
                            if (x == 0 && z == 0) continue;
                            
                            var neighbor = position + new Vector3(x * gridSize, 0, z * gridSize);
                            if (IsValidPosition(neighbor, spatialMemory))
                            {
                                neighbors.Add(neighbor);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"[PathFinder] Error getting neighbors: {ex.Message}");
            }
            
            return neighbors;
        }
        
        /// <summary>
        /// 检查位置是否有效
        /// </summary>
        private bool IsValidPosition(Vector3 position, SpatialMemory spatialMemory)
        {
            // 简化的碰撞检测
            // 在实际实现中，这里应该检查Unity的碰撞器或地形
            
            // 基本边界检查
            if (position.y < -10 || position.y > 100)
                return false;
            
            // 如果有空间记忆，检查是否在可达区域内
            if (spatialMemory != null)
            {
                var nearestNode = spatialMemory.GetAllSpatialNodes().Values
                    .OrderBy(n => Vector3.Distance(n.position, position))
                    .FirstOrDefault();
                
                if (nearestNode != null && Vector3.Distance(nearestNode.position, position) > 50f)
                {
                    return false; // 太远离已知区域
                }
            }
            
            return true;
        }
        
        /// <summary>
        /// 重构路径
        /// </summary>
        private List<Vector3> ReconstructPath(Dictionary<Vector3, Vector3> cameFrom, Vector3 current, Vector3 start)
        {
            var path = new List<Vector3> { current };
            
            while (cameFrom.ContainsKey(current))
            {
                current = cameFrom[current];
                path.Add(current);
            }
            
            path.Reverse();
            return path;
        }
        
        /// <summary>
        /// 优化路径
        /// </summary>
        private List<Vector3> OptimizePath(List<Vector3> originalPath)
        {
            if (originalPath == null || originalPath.Count <= 2)
            {
                return originalPath;
            }
            
            try
            {
                var optimizedPath = new List<Vector3> { originalPath[0] };
                
                for (int i = 1; i < originalPath.Count - 1; i++)
                {
                    var prev = optimizedPath.Last();
                    var current = originalPath[i];
                    var next = originalPath[i + 1];
                    
                    // 如果三点几乎共线，跳过中间点
                    var angle = Vector3.Angle(current - prev, next - current);
                    if (angle > 10f) // 如果转角大于10度，保留这个点
                    {
                        optimizedPath.Add(current);
                    }
                }
                
                optimizedPath.Add(originalPath.Last());
                
                // 平滑路径
                return SmoothPath(optimizedPath);
            }
            catch (Exception ex)
            {
                Debug.LogError($"[PathFinder] Error optimizing path: {ex.Message}");
                return originalPath;
            }
        }
        
        /// <summary>
        /// 平滑路径
        /// </summary>
        private List<Vector3> SmoothPath(List<Vector3> path)
        {
            if (path.Count <= 2)
                return path;
            
            try
            {
                var smoothedPath = new List<Vector3> { path[0] };
                
                for (int i = 1; i < path.Count - 1; i++)
                {
                    var prev = path[i - 1];
                    var current = path[i];
                    var next = path[i + 1];
                    
                    // 使用简单的平均平滑
                    var smoothed = (prev + current * 2 + next) / 4f;
                    smoothedPath.Add(smoothed);
                }
                
                smoothedPath.Add(path.Last());
                return smoothedPath;
            }
            catch (Exception ex)
            {
                Debug.LogError($"[PathFinder] Error smoothing path: {ex.Message}");
                return path;
            }
        }
        
        /// <summary>
        /// 创建直线路径
        /// </summary>
        private List<Vector3> CreateDirectPath(Vector3 start, Vector3 end)
        {
            var path = new List<Vector3> { start };
            
            var distance = Vector3.Distance(start, end);
            var segmentCount = Mathf.Max(2, Mathf.RoundToInt(distance / 5f)); // 每5米一个点
            
            for (int i = 1; i < segmentCount; i++)
            {
                var t = (float)i / segmentCount;
                var point = Vector3.Lerp(start, end, t);
                path.Add(point);
            }
            
            path.Add(end);
            return path;
        }
        
        /// <summary>
        /// 生成缓存键
        /// </summary>
        private string GenerateCacheKey(Vector3 start, Vector3 end)
        {
            return $"{start.x:F1},{start.z:F1}-{end.x:F1},{end.z:F1}";
        }
        
        /// <summary>
        /// 尝试获取缓存路径
        /// </summary>
        private bool TryGetCachedPath(string cacheKey, out List<Vector3> path)
        {
            path = null;
            
            if (cachedPaths.TryGetValue(cacheKey, out var cachedPath) &&
                pathCacheTimestamps.TryGetValue(cacheKey, out var timestamp))
            {
                // 检查缓存是否过期
                if ((DateTime.Now - timestamp).TotalSeconds <= pathCacheLifetime)
                {
                    path = new List<Vector3>(cachedPath);
                    return true;
                }
                else
                {
                    // 清理过期缓存
                    cachedPaths.Remove(cacheKey);
                    pathCacheTimestamps.Remove(cacheKey);
                }
            }
            
            return false;
        }
        
        /// <summary>
        /// 缓存路径
        /// </summary>
        private void CachePath(string cacheKey, List<Vector3> path)
        {
            try
            {
                // 限制缓存大小
                if (cachedPaths.Count >= maxCacheSize)
                {
                    CleanupOldestCache();
                }
                
                cachedPaths[cacheKey] = new List<Vector3>(path);
                pathCacheTimestamps[cacheKey] = DateTime.Now;
            }
            catch (Exception ex)
            {
                Debug.LogError($"[PathFinder] Error caching path: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 清理最旧的缓存
        /// </summary>
        private void CleanupOldestCache()
        {
            if (pathCacheTimestamps.Count == 0) return;
            
            var oldestKey = pathCacheTimestamps
                .OrderBy(kv => kv.Value)
                .First().Key;
            
            cachedPaths.Remove(oldestKey);
            pathCacheTimestamps.Remove(oldestKey);
        }
        
        /// <summary>
        /// 清理过期缓存
        /// </summary>
        public void CleanupExpiredCache()
        {
            try
            {
                var cutoffTime = DateTime.Now.AddSeconds(-pathCacheLifetime);
                var expiredKeys = pathCacheTimestamps
                    .Where(kv => kv.Value < cutoffTime)
                    .Select(kv => kv.Key)
                    .ToList();
                
                foreach (var key in expiredKeys)
                {
                    cachedPaths.Remove(key);
                    pathCacheTimestamps.Remove(key);
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"[PathFinder] Error cleaning up expired cache: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 估算路径长度
        /// </summary>
        public float EstimatePathLength(Vector3 start, Vector3 end, SpatialMemory spatialMemory)
        {
            try
            {
                var path = FindPath(start, end, spatialMemory);
                return CalculatePathLength(path);
            }
            catch (Exception ex)
            {
                Debug.LogError($"[PathFinder] Error estimating path length: {ex.Message}");
                return Vector3.Distance(start, end);
            }
        }
        
        /// <summary>
        /// 计算路径长度
        /// </summary>
        private float CalculatePathLength(List<Vector3> path)
        {
            if (path == null || path.Count < 2)
                return 0f;
            
            float totalLength = 0f;
            for (int i = 1; i < path.Count; i++)
            {
                totalLength += Vector3.Distance(path[i - 1], path[i]);
            }
            
            return totalLength;
        }
        
        /// <summary>
        /// 估算路径时间
        /// </summary>
        public float EstimatePathTime(Vector3 start, Vector3 end, SpatialMemory spatialMemory, float movementSpeed = 2f)
        {
            var pathLength = EstimatePathLength(start, end, spatialMemory);
            return pathLength / movementSpeed;
        }
        
        /// <summary>
        /// 检查路径是否可达
        /// </summary>
        public bool IsPathAccessible(Vector3 start, Vector3 end, SpatialMemory spatialMemory)
        {
            try
            {
                var path = FindPath(start, end, spatialMemory);
                return path != null && path.Count > 1 && Vector3.Distance(path.Last(), end) < 5f;
            }
            catch (Exception ex)
            {
                Debug.LogError($"[PathFinder] Error checking path accessibility: {ex.Message}");
                return false;
            }
        }
        
        /// <summary>
        /// 清空缓存
        /// </summary>
        public void ClearCache()
        {
            cachedPaths.Clear();
            pathCacheTimestamps.Clear();
        }
        
        /// <summary>
        /// 获取缓存统计信息
        /// </summary>
        public string GetCacheStats()
        {
            return $"Cached paths: {cachedPaths.Count}/{maxCacheSize}, Cache lifetime: {pathCacheLifetime}s";
        }
        
        /// <summary>
        /// 设置缓存参数
        /// </summary>
        public void SetCacheParameters(int maxSize, float lifetimeSeconds)
        {
            maxCacheSize = maxSize;
            pathCacheLifetime = lifetimeSeconds;
        }
    }
    
    /// <summary>
    /// 路径节点类
    /// </summary>
    public class PathNode
    {
        public Vector3 position;
        public float gScore; // 从起点到当前节点的实际距离
        public float hScore; // 从当前节点到终点的启发式距离
        public float fScore; // gScore + hScore
    }
}